#include "mystdio.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <malloc.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>

LJK_FILE *my_fopen(const char *path, const char *mode){
  //1.识别标志位
  int flag = 0;
  if (strcmp(mode, "r") == 0){
    flag |= O_RDONLY;
  }else if (strcmp(mode, "w") == 0){
    flag |= (O_CREAT|O_WRONLY|O_TRUNC);
  }else if (strcmp(mode, "a") == 0){
    flag |= (O_CREAT|O_WRONLY|O_APPEND);
  }else{
    //other operator
    //"r+" "w+" "a+"...
  }

  //2.尝试打开文件
  umask(0);
  mode_t m = 0666;
  
  int fd = 0;
  if (flag & O_CREAT){
    fd = open(path, flag, m);
  }else{
    fd = open(path, flag);
  }

  if (fd < 0){
    return NULL;
  }

  //3.给用户返回LJK_FILE对象
  LJK_FILE* mf = (LJK_FILE*)malloc(sizeof(LJK_FILE));
  if (mf == NULL){
    close(fd);
    return NULL;
  }

  //4.初始化LJK_FILE对象,这里就不实现刷新方式转换了，默认为行刷新
  mf->fd = fd;
  mf->flags = BUFF_LINE;
  memset(mf->outputbuffer, '\0', sizeof(mf->outputbuffer));
  mf->current = 0;
  //mf->outputbuffer[0] = 0;//初始化缓冲区

  //5.返回打开的文件
  return mf;
}
int my_fflush(LJK_FILE* fp){
  assert(fp);

  //将用户级缓冲区数据，通过系统调用冲刷给操作系统
  write(fp->fd, fp->outputbuffer, fp->current);
  fp->current = 0;
  //todo...
  //强制刷新到内核函数
  fsync(fp->fd);
  return 0;
}

//我们今天返回的就是一次写入的字节数，就不返回个数了
size_t my_fwrite(const void *ptr, size_t size, size_t nmemb,LJK_FILE *stream){
  //1.缓冲区如果已经满了就直接写入
  if (stream->current == NUM) {
    my_fflush(stream);
  }
  //2.根据缓冲区剩余情况，进行数据拷贝即可
  size_t user_size = size * nmemb;
  size_t my_size = NUM - stream->current;//100 - 10 = 90

  size_t writen = 0;
  if (my_size >= user_size){
    memcpy(stream->outputbuffer+stream->current, ptr, user_size);
    //3.更新计数器字段
    stream->current += user_size;
    writen = user_size;
  }else{ 
    memcpy(stream->outputbuffer+stream->current, ptr, my_size);
    //3.更新计数器字段
    stream->current += my_size;
    writen = my_size;
  }

  //4.开始计划刷新, 高效体现在哪里
  //不发生刷新的本质，不进行写入，就是不进行IO，不进行系统调用，所以my_fwriteh函数调用会非常快，数据暂时保存在缓冲区中，可以在缓冲区中挤压多分数据，统一进行写入，本质就是一次IO可以IO更多的数据, 提高IO效率
  if (stream->flags & BUFF_ALL){
    if (stream->current == NUM) my_fflush(stream);
  }else if (stream->flags & BUFF_LINE){
    if (stream->outputbuffer[stream->current - 1] == '\n'){
      my_fflush(stream);
    }
  }else{
    //...
  }

  return writen;
}
int my_fclose(LJK_FILE *fp){
  assert(fp);

  //1.冲刷缓冲区
  if (fp->current > 0){
    my_fflush(fp);
  }
  //2.关闭文件
  close(fp->fd);
  //3.释放堆空间
  free(fp);
  //4.指针设置NULL(最好设置)
  fp = NULL;

  return 0;
}

//int my_scanf(); stdin -> buffer -> 对buffer内容进行格式化，写到对应的变量中
//int a,b; scanf("%d %d", &a, &b); read(0), stdin -> buffer, num); -> 123 456 -> 输入的本质：输入的也是字符
//扫描字符串，碰到空格， 字符串分割成两个子串， *ap = atoi(str); *bp = atoi(str2);

//int my_printf(const char* format, ...){
//  //1.先获取对应的变量 a
//  //2.定义缓冲区，对a转成字符串
//  //3.将字符串拷贝的stdout -> buffer即可
//  //4.结合刷新策略显示即可
//}
